#include "assert.h"
#include "error.h"
#include "stdio.h"
#include "lock.h"
#include "proc.h"
#include "trap.h"

#include "fs/deffs.h"
#include "fs/inode.h"
#include "fs/vfs.h"
#include "fs/iobuf.h"
#include "fs/device.h"

static int
stdout_open(device_t* dev, uint32_t flags) {
    if (flags != O_WRONLY)
        return -E_INVAL;
    return 0;
}

static int
stdout_close(device_t* dev) {
    return 0;
}

static int
stdout_io(device_t* dev, iobuf_t* iob, bool write) {
    if (!write)
        return -E_INVAL;

    char* data = iob->io_base;
    for (; iob->io_resid > 0; --iob->io_resid) {
        putchar(*data);
        ++data;
    }
    return 0;
}

static int
stdout_ioctl(device_t* dev, int op, void* data) {
    return -E_INVAL;
}

void
dev_init_stdout(void) {
    inode_t* node = dev_createInode();
    if (node == NULL)
        panic("stdout: dev_create_node\n");

    device_t* dev = vop_info(node, device);
    dev->d_blocks = 0;  // char device
    dev->d_blocksize = 1;
    dev->d_open = stdout_open;
    dev->d_close = stdout_close;
    dev->d_io = stdout_io;
    dev->d_ioctl = stdout_ioctl;

    int ret = vfs_addDevice("stdout", node, 0);
    if (ret != 0)
        panic("stdout: vfs_add_dev\n");
}